package org.groupg.project.server;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.util.concurrent.DefaultThreadFactory;
import org.groupg.project.config.ProxyConfig;
import org.groupg.project.config.RuleConfig;
import org.groupg.project.handler.ProxyFrontendHandler;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class HttpProxyServer {
    private final ProxyConfig config;
    private List<Channel> serverChannels = new ArrayList<>();
    private EventLoopGroup bossGroup;
    private EventLoopGroup workerGroup;

    public HttpProxyServer(ProxyConfig config) {
        this.config = config;
    }

    public void start() throws InterruptedException {
        bossGroup = new NioEventLoopGroup(1, new DefaultThreadFactory("proxy-boss"));
        workerGroup = new NioEventLoopGroup(0, new DefaultThreadFactory("proxy-worker"));

        try {
            // 保存所有端口的ChannelFuture
            List<ChannelFuture> serverFutures = new ArrayList<>();

            // 为每个端口创建服务器
            for (Map.Entry<Integer, List<RuleConfig>> entry : config.getPortRules().entrySet()) {
                int port = entry.getKey();
                List<RuleConfig> rules = entry.getValue();

                ServerBootstrap b = new ServerBootstrap();
                b.group(bossGroup, workerGroup)
                        .channel(NioServerSocketChannel.class)
                        .childHandler(new ChannelInitializer<SocketChannel>() {
                            @Override
                            protected void initChannel(SocketChannel ch) {
                                ChannelPipeline p = ch.pipeline();
                                p.addLast(new HttpServerCodec());
                                p.addLast(new HttpObjectAggregator(65536));
                                p.addLast(new ProxyFrontendHandler(rules));
                            }
                        })
                        .option(ChannelOption.SO_BACKLOG, 128)
                        .childOption(ChannelOption.AUTO_READ, false);

                ChannelFuture f = b.bind(port).sync();
                serverFutures.add(f);
                System.out.println("Proxy server started on port " + port);
            }

            // 添加关闭钩子
            Runtime.getRuntime().addShutdownHook(new Thread(this::shutdown));

            // 等待所有服务器关闭
            for (ChannelFuture f : serverFutures) {
                f.channel().closeFuture().sync();
            }
        } finally {
            shutdown();
        }
    }

    private void shutdown() {
        if (bossGroup != null) {
            bossGroup.shutdownGracefully();
        }
        if (workerGroup != null) {
            workerGroup.shutdownGracefully();
        }
        System.out.println("Proxy server stopped");
    }

    public List<Channel> getServerChannels() {
        return serverChannels;
    }
}